//*****************************************************************************
// JFab (http://code.google.com/p/jfab)
// Copyright (c) 2011 JFab.org
// Admin jfab@jeffreythompson.net
//
// See the file "LICENSE.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//*****************************************************************************

package org.jfab.core.builder;

import org.jfab.core.analyzer.AnalyzerInjector;
import org.jfab.core.analyzer.ClassAnalyzer;
import org.jfab.core.analyzer.DefaultAnalyzerInjector;
import org.jfab.core.comparator.CGConstructorComparator;
import org.jfab.core.comparator.CGFieldComparator;
import org.jfab.core.comparator.CGMethodComparator;
import org.jfab.core.comparator.ComparatorInjector;
import org.jfab.core.comparator.DefaultComparatorInjector;
import org.jfab.core.factory.CGAnnotationFactory;
import org.jfab.core.factory.CGClassFactory;
import org.jfab.core.factory.CGConstructorFactory;
import org.jfab.core.factory.CGFieldFactory;
import org.jfab.core.factory.CGMethodFactory;
import org.jfab.core.factory.CGParameterFactory;
import org.jfab.core.factory.CGTypeFactory;
import org.jfab.core.factory.DefaultFactoryInjector;
import org.jfab.core.factory.FactoryInjector;
import org.jfab.core.factory.InstanceFactory;
import org.jfab.core.factory.StringFactory;
import org.jfab.core.factory.TypeReferenceSupport;
import org.jfab.core.model.CGTypeUtilities;
import org.jfab.core.model.DefaultModelInjector;
import org.jfab.core.model.ModelInjector;

/**
 * Provides a default builder injector.
 */
public class DefaultBuilderInjector implements BuilderInjector
{
    /** Analyzer injector. */
    private final AnalyzerInjector _analyzerInjector;

    /** Comparator injector. */
    private final ComparatorInjector _comparatorInjector;

    /** Factory injector. */
    private final FactoryInjector _factoryInjector;

    /** Model injector. */
    private final ModelInjector _modelInjector;

    /**
     * Construct this object.
     */
    public DefaultBuilderInjector()
    {
        this(new DefaultAnalyzerInjector(), new DefaultComparatorInjector(),
                new DefaultFactoryInjector(), new DefaultModelInjector());
    }

    /**
     * Construct this object with the given parameters.
     * 
     * @param analyzerInjector Analyzer injector.
     * @param comparatorInjector Comparator injector.
     * @param factoryInjector Factory injector.
     * @param modelInjector Model injector.
     */
    public DefaultBuilderInjector(final AnalyzerInjector analyzerInjector,
            final ComparatorInjector comparatorInjector,
            final FactoryInjector factoryInjector,
            final ModelInjector modelInjector)
    {
        _analyzerInjector = analyzerInjector;
        _comparatorInjector = comparatorInjector;
        _factoryInjector = factoryInjector;
        _modelInjector = modelInjector;
    }

    @Override
    public BuilderGroup injectBuilderGroup()
    {
        return new BuilderGroup(injectConverterCGClassBuilder(),
                injectJUnitTestCGClassBuilder(),
                injectSimulatedDataCGClassBuilder());
    }

    @Override
    public ConverterCGClassBuilder injectConverterCGClassBuilder()
    {
        return new ConverterCGClassBuilder(injectCGTypeUtilities(),
                injectCGTypeFactory(), injectTypeReferenceSupport(),
                injectCGParameterFactory(), injectCGMethodFactory(),
                injectCGMethodComparator(), injectCGClassFactory());
    }

    @Override
    public DecoratorCGClassBuilder injectDecoratorCGClassBuilder()
    {
        return new DecoratorCGClassBuilder(injectCGTypeUtilities(),
                injectStringFactory(), injectCGAnnotationFactory(),
                injectCGParameterFactory(), injectCGFieldFactory(),
                injectCGFieldComparator(), injectCGConstructorFactory(),
                injectCGConstructorComparator(), injectCGMethodFactory(),
                injectCGMethodComparator(), injectCGClassFactory(),
                injectClassAnalyzer());
    }

    @Override
    public JUnitTestCGClassBuilder injectJUnitTestCGClassBuilder()
    {
        return new JUnitTestCGClassBuilder(injectCGTypeFactory(),
                injectCGClassFactory());
    }

    @Override
    public SimulatedDataCGClassBuilder injectSimulatedDataCGClassBuilder()
    {
        return new SimulatedDataCGClassBuilder(injectCGTypeUtilities(),
                injectCGTypeFactory(), injectStringFactory(),
                injectCGMethodFactory(), injectCGMethodComparator(),
                injectCGClassFactory(), injectInstanceFactory());
    }

    /**
     * @return the analyzerInjector
     */
    private AnalyzerInjector getAnalyzerInjector()
    {
        return _analyzerInjector;
    }

    /**
     * @return the comparatorInjector
     */
    private ComparatorInjector getComparatorInjector()
    {
        return _comparatorInjector;
    }

    /**
     * @return the factoryInjector
     */
    private FactoryInjector getFactoryInjector()
    {
        return _factoryInjector;
    }

    /**
     * @return the modelInjector
     */
    private ModelInjector getModelInjector()
    {
        return _modelInjector;
    }

    /**
     * @return a new annotation factory.
     */
    private CGAnnotationFactory injectCGAnnotationFactory()
    {
        return getFactoryInjector().injectCGAnnotationFactory();
    }

    /**
     * @return a new class factory.
     */
    private CGClassFactory injectCGClassFactory()
    {
        return getFactoryInjector().injectCGClassFactory();
    }

    /**
     * @return a new constructor comparator.
     */
    private CGConstructorComparator injectCGConstructorComparator()
    {
        return getComparatorInjector().injectCGConstructorComparator();
    }

    /**
     * @return a new constructor factory.
     */
    private CGConstructorFactory injectCGConstructorFactory()
    {
        return getFactoryInjector().injectCGConstructorFactory();
    }

    /**
     * @return a new field comparator.
     */
    private CGFieldComparator injectCGFieldComparator()
    {
        return getComparatorInjector().injectCGFieldComparator();
    }

    /**
     * @return a new field factory.
     */
    private CGFieldFactory injectCGFieldFactory()
    {
        return getFactoryInjector().injectCGFieldFactory();
    }

    /**
     * @return a new method comparator.
     */
    private CGMethodComparator injectCGMethodComparator()
    {
        return getComparatorInjector().injectCGMethodComparator();
    }

    /**
     * @return a new method factory.
     */
    private CGMethodFactory injectCGMethodFactory()
    {
        return getFactoryInjector().injectCGMethodFactory();
    }

    /**
     * @return a new code generator parameter factory.
     */
    private CGParameterFactory injectCGParameterFactory()
    {
        return getFactoryInjector().injectCGParameterFactory();
    }

    /**
     * @return a new type factory.
     */
    private CGTypeFactory injectCGTypeFactory()
    {
        return getFactoryInjector().injectCGTypeFactory();
    }

    /**
     * @return a new type utilities.
     */
    private CGTypeUtilities injectCGTypeUtilities()
    {
        return getModelInjector().injectCGTypeUtilities();
    }

    /**
     * @return a new class analyzer.
     */
    private ClassAnalyzer injectClassAnalyzer()
    {
        return getAnalyzerInjector().injectClassAnalyzer();
    }

    /**
     * @return a new instance factory.
     */
    private InstanceFactory injectInstanceFactory()
    {
        return getFactoryInjector().injectInstanceFactory();
    }

    /**
     * @return a new string factory.
     */
    private StringFactory injectStringFactory()
    {
        return getFactoryInjector().injectStringFactory();
    }

    /**
     * @return a new type reference support.
     */
    private TypeReferenceSupport injectTypeReferenceSupport()
    {
        return getFactoryInjector().injectTypeReferenceSupport();
    }
}
